home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-13 / emac16ds.zip / MINTSCAN.ASM < prev    next >
Assembly Source File  |  1991-08-03  |  16KB  |  613 lines

  1. ;History:515,22
  2. ;Thu Jun 13 23:42:01 1991 Move the stack to the code segment.
  3. ;Tue Dec 19 22:40:56 1989 Add an ifdef for 'timing' to disable the profiling code.
  4. ;Sun Nov 12 22:51:36 1989 add profiling to the code.
  5. ;Thu Sep 14 23:26:52 1989 Add make_active and remove return_arg_active.
  6. ;12-12-87 13:41:44 bum a lot of instructions out of scan_loop.
  7. ;12-07-87 20:09:39 add store_debug
  8. ;11-23-87 22:20:47 use scan_copy as the base of scan_xlat_table.
  9.     page    ,132
  10.  
  11.     .xlist
  12.     include    emacs.def
  13.     include mint.def
  14.     .list
  15.  
  16. HT    equ    9
  17. LF    equ    10
  18. CR    equ    13
  19.  
  20. code    segment    byte public
  21. code    ends
  22.  
  23. data    segment byte public
  24. data    ends
  25.  
  26. bufseg    segment public
  27.     public    prev_buffer, next_buffer, toptop, topbot, bottop, botbot, new_size
  28.     define_buffer
  29. bufseg    ends
  30.  
  31. data    segment byte public
  32.     public    data_bottop, data_topbot, data_botbot
  33.     define_buffer    data_
  34. data    ends
  35.  
  36. data    segment byte public
  37.  
  38. comment /******************************************************************
  39.  
  40. Introduction:
  41.  
  42.     The MINT data structures are laid out in memory as given below.
  43. First are the variables, followed by the neutral string.  Next is the
  44. block of free memory.
  45.  
  46.     variables, neutral string ... free memory ... neutral string.
  47.  
  48. The neutral string:
  49.  
  50.     The neutral string consists of a list of arguments.  Each argument
  51. begins with header which might be laid out as so in Pascal:
  52.     arg_header = record
  53.      marker : (active_marker, neutral_marker, comma_marker);
  54.      previous : ^arg_header;
  55.     end;
  56.  
  57. The pointer, previous, points to the previous arg_header. The last one in the
  58. list has a nil pointer.  This will always be the #(ps) which is the outermost
  59. function to be executed.
  60.  
  61. The neutral string during function execution:
  62.  
  63.     Since we are interested in counting arguments from left to right,
  64. not right to left, we need to reverse the pointers so that they point
  65. from the first argument, to the second argument, to the third argument,
  66. etc.  At this point, [fbgn] points to the first argument (the name of the
  67. funciton), and [fend] points past the last argument.  To make argument
  68. fetching more efficient, the last argument is followed by a null argument
  69. which points to itself.  This causes missing arguments to be fetched as
  70. nulls, in according to the definition of the language.
  71.     Functions which return a value will build that value at either
  72. [fbgn]-1 or [fend]-2, depending on whether or not they need to refer to
  73. arguments supplied to the function.  In general, single argument functions
  74. will use [fbgn]-1, and multiple argument functions will use [fend]-2.
  75.  
  76. Neutral function results will eventually be moved to [fbgn]-1.
  77.  
  78. The active string:
  79.  
  80.     The active string consists of a string of ASCII characters which
  81. have not yet been scanned.  Typically, only ASCII characters appear here,
  82. although any eight bit value may occur.
  83.  
  84. The active string during function execution:
  85.  
  86.     [actptr] points to the end of the active string.  Active function
  87. results are built as described above and then moved to the left of [actptr].
  88. Actptr is then adjusted to point to the result just moved in.  Primitives
  89. check for memory overflow by comparing [fend] to [actptr].  If they come
  90. closer than some magic constant, then the 'No Memory' error is given
  91. and the idling string is reloaded.
  92.  
  93.  
  94. **************************************************************************/
  95.  
  96.  
  97.     public    trace
  98.     public    next_ids
  99.     extrn    standard_ids: byte
  100.     public    fbgn, fend
  101.     extrn    lomem: byte
  102.  
  103. trace    db    0        ;trace is initially off.
  104. next_ids    dw    standard_ids
  105. fbgn    dw    ?
  106. fend    dw    ?
  107. fcn_save    db    ?
  108. prev_fcn    dw    ?
  109.  
  110. ;some constant definitions
  111.  
  112. ;the _mark constants mark where a particular type of string occurs in
  113. ; the linked list.
  114.  
  115. comma_marker    equ    0    ;comma_marker must not have function_marker_mask set!
  116. active_marker    equ    1    ;active_marker must have function_marker_mask set!
  117. neutral_marker    equ    3    ;neutral_marker must have function_marker_mask set!
  118. function_marker_mask    equ    1
  119.  
  120. entry    macro    char, adr
  121.     org    (offset scan_xlat_table)+char
  122.     db    (offset adr) - (offset scan_copy)
  123.     endm
  124.  
  125.     db    0
  126. scan_xlat_table    db    256 dup (0)
  127. ;first, fill up the table with 'copy'
  128. ;next, put the proper addresses in the right spots,
  129.     entry    HT,scan_ignore
  130.     entry    CR,scan_ignore
  131.     entry    LF,scan_ignore
  132.     entry    '#',scan_sharp
  133.     entry    '(',scan_lpar
  134.     entry    ')',scan_rpar
  135.     entry    ',',scan_comma
  136. ;finally, go to the end of the table.
  137.     org    (offset scan_xlat_table)+(size scan_xlat_table)
  138.  
  139.     purge    entry
  140.  
  141.     extrn    function_name_table: word
  142.     extrn    function_name_length: abs
  143.     extrn    function_address: word
  144.  
  145.   if timing
  146.     extrn    counting: byte
  147.  
  148.     public    counts
  149. counts    dw    100 dup(0)
  150.  
  151.     public    times
  152. times    dw    100 dup(0)
  153.   endif
  154.  
  155. nomem_prompt        db    'No memory!',0
  156. fatal_prompt        db    'No disk in drive or door open!',0
  157. protected_prompt    db    'Disk is write protected!',0
  158.  
  159. buffers_bad_msg    db    'Buffers corrupted, reboot:','$'
  160. buffers_be_msg    db    'xx will say Buffers corrupted, reboot:','$'
  161.  
  162.     extrn    stackp: byte
  163.  
  164. data    ends
  165.  
  166. code    segment byte public
  167.  
  168.     assume    cs:code, ds:data, es:data
  169.  
  170. comment /*******************************************************************
  171.     The following is the MINT scan loop.  This loop must be as fast as
  172. possible because it is executed the most often.   As a consequence, the
  173. code is quite unstructured.  However, the code follows the algorithm given in
  174. the MINT language definition document.
  175.     During scan, si -> (points to) the active string, di -> the
  176. neutral string, dx -> previous argument, and bp -> end of active string.
  177.     As we scan a character, we must branch to certain routines on certain
  178. characters.  To make best use of the 8086 instruction set, we have set up a
  179. translate table.  Therefore, the translate table, scan_xlat_table, contains an
  180. offset from the beginning of the scan loop.
  181.  
  182.     When the scan loop has finally found a function to be executed,
  183. a jump is performed to that primitive (unknown primitives cause jump to dflt).
  184. When the primitive is finished, it jumps (with the exception of hl) to one of
  185. the 'return_???' functions.  Each of the return_??? routines puts the returned
  186. value in the proper place in the proper string (active or neutral), and jumps
  187. back to scan.
  188.     The scan loop is repeatedly executed until there are no more functions
  189. to be executed, or the available memory has been exhausted.
  190. *****************************************************************************/
  191.  
  192. scan_copy:            ;come here to copy a char from active to neutral
  193. scan_loop:
  194.     lodsb            ;movsb loses because it doesn't load AL.
  195.     stosb
  196.     xlat            ;al was char, is now offset
  197.     jmp    ax
  198.  
  199. scan_ignore:            ;come here to throw a char away from active.
  200.     dec    di
  201.     jmp    scan_loop
  202.  
  203. scan_lpar:
  204.     dec    di            ;uncopy the '('
  205.     mov    cx,1
  206. scan_lpar_1:
  207.     lodsb            ;can't use movsb, because it doesn't load al
  208.     stosb
  209.     cmp    al,'('
  210.     je    scan_lpar_2
  211.     cmp    al,')'
  212.     jne    scan_lpar_1
  213.     cmp    si,bp            ;was this our sentinel?
  214.     je    init_ids_jump_2        ;yes - we're gone.
  215.     loop    scan_lpar_1
  216.     dec    di        ;remove final rpar
  217.     mov    ax,offset scan_copy
  218.     jmp    scan_loop
  219. scan_lpar_2:
  220.     inc    cx
  221.     jmp    scan_lpar_1
  222. init_ids_jump_2:
  223.     jmp    init_ids
  224.  
  225. scan_rpar:
  226. ;si -> neutral string
  227. ;di -> active string
  228. ;dx -> previous argument or function pointer.
  229.     dec    di            ;uncopy the ')'
  230.     cmp    si,bp            ;if we scan off the right end, init_ids
  231.     je    init_ids_jump_2
  232.     profile    4
  233.     call    scan_rpar_sub
  234.   if 0
  235.     call    buffer_check
  236.     jnz    buffers_be_bad
  237.   endif
  238.   if timing
  239.     call    readtimer        ;subtract off the start time.
  240.     sub    times[di-2],ax
  241.     inc    counts[di-2]
  242.     push    di
  243.   endif
  244.     profile    2
  245.     call    function_address[di-2]
  246.   if timing
  247.     call    readtimer        ;add in the finishing time
  248.     pop    bx
  249.     add    times[bx-2],ax
  250.   endif
  251.     extrn    buffer_check: near
  252.   if 0
  253.     call    buffer_check
  254.     jnz    buffers_bad
  255.   endif
  256.     profile    1
  257.     mov    bp,data_botbot
  258.     mov    bx,offset scan_xlat_table    ;->translate table
  259.     mov    ax,offset scan_copy
  260.     jmp    scan_loop
  261. buffers_be_bad:
  262.     mov    word ptr buffers_be_msg,ax
  263. buffers_be_bad_1:
  264.     mov    dx,offset buffers_bad_msg
  265.     mov    ah,9
  266.     int    21h
  267.     mov    ah,7
  268.     int    21h
  269.     jmp    buffers_be_bad_1
  270. buffers_bad:
  271.     mov    dx,offset buffers_bad_msg
  272.     mov    ah,9
  273.     int    21h
  274.     mov    ah,7
  275.     int    21h
  276.     jmp    buffers_bad
  277.  
  278. scan_comma:
  279.     mov    al,comma_marker
  280. scan_mark:
  281.     mov    [di-1],al    ;store marker where the character was copied.
  282.     mov    ax,dx        ;get previous pointer
  283.     mov    dx,di        ;save current (will soon be previous)
  284.     stosw
  285.     mov    ax,offset scan_copy
  286. scan_copy_j_1:
  287.     jmp    scan_loop
  288.  
  289. scan_sharp:
  290.     cmp    word ptr [si],'(#'    ;'##(' ?
  291.     je    scan_two_sharps        ;yes.
  292.     cmp    byte ptr [si],'('    ;'#(' ?
  293.     jne    scan_copy_j_1        ;no.
  294.     inc    si
  295.     mov    al,active_marker
  296.     jmp    scan_mark
  297. scan_two_sharps:
  298.     add    si,2
  299.     mov    al,neutral_marker
  300.     jmp    scan_mark
  301.  
  302.     public    abort_fatal
  303. abort_fatal:
  304.     add    sp,22            ;magic number from Z-DOS II, page I.3
  305.     pop    es            ;restore our es and ds.
  306.     push    es
  307.     pop    ds
  308.     mov    sp,offset stackp
  309.     sti                ;enable interrupts again.
  310.     mov    si,offset protected_prompt
  311.     cmp    di,0            ;write protect?
  312.     je    nomem_1
  313.     mov    si,offset fatal_prompt
  314.     jmp    short nomem_1
  315.     public    nomem
  316. nomem:
  317.     esdata
  318.     dsdata
  319.     mov    sp,offset stackp
  320.     mov    si,offset nomem_prompt
  321. nomem_1:
  322.     lodsb
  323.     or    al,al
  324.     je    nomem_2
  325.     mov    dl,al
  326.     mov    ah,2
  327.     int    21h
  328.     jmp    nomem_1
  329. nomem_2:
  330.     jmp    init_ids
  331.  
  332.     extrn    init_ids: near
  333.     extrn    buffer_free: near
  334.  
  335.     public    init_ids_continue, init_ids_first
  336. init_ids_continue:
  337.     cld
  338.     mov    ax,data_botbot        ;get rid of the active string.
  339.     mov    data_bottop,ax
  340.     mov    data_topbot,offset lomem;get rid of the neutral string.
  341.     mov    di,next_ids        ;get the desired idling string.
  342.     mov    si,di            ;save a copy
  343.     mov    next_ids,offset standard_ids    ;reset to ids.
  344.     mov    al,0
  345.     mov    cx,-1
  346.     repne    scasb        ;find the terminating null.
  347.     not    cx
  348.     mov    ax,ds
  349.     call    buffer_free
  350.     mov    di,data_botbot
  351.     sub    di,cx
  352.     dec    di            ;leave room for a sentinel
  353.     mov    data_bottop,di
  354.     rep    movsb
  355.     mov    al,')'            ;use an extra ')' as a sentinel
  356.     stosb
  357. init_ids_first:
  358.     mov    cx,256            ;get at least a little bit of room.
  359.     mov    ax,ds
  360.     call    buffer_free
  361.     profile    1
  362.     mov    si,data_bottop
  363.     mov    di,data_topbot
  364.     mov    dx,0
  365.     mov    bp,data_botbot
  366.     mov    bx,offset scan_xlat_table    ;->translate table
  367.     mov    ax,offset scan_copy
  368.     jmp    scan_loop
  369. init_ids_jump_1:
  370.     jmp    init_ids
  371.  
  372.  
  373.     public    scan_rpar_sub
  374. scan_rpar_sub:
  375. ;store last argument mark
  376.     mov    al,comma_marker
  377.     stosb
  378.     mov    ax,di        ;make final arg -> itself
  379.     stosw
  380. comment @can't use slash***************************************************
  381.     We have a problem here.  Currently, the pointers point backwards
  382. to the previous function/arg.  We want this function's pointers to point
  383. forwards, so we can start at the active/neutral marker and count arguments
  384. forwards.
  385.  
  386.      __ is a pointer, ^ is what it points to.
  387.  
  388.  
  389.     a__SS,__ONE,__TWO,__
  390.       ^    ^    !^    !^
  391.       !   !!    !!    !!
  392.       \___/\____/!    \/
  393.              dx
  394. **********************************************************************@
  395.     mov    fend,di
  396.     mov    data_topbot,di
  397.     sub    di,2        ;make di ->final pointer
  398.     mov    data_bottop,si
  399. scan_rpar_1:
  400.     cmp    dx,0        ;if end of list, we must be running off
  401.     je    init_ids_jump_1    ; the left end (too many rpars)
  402.     mov    bx,dx        ;get previous pointer.
  403.     mov    dx,[bx]        ;get the current pointer [previous pointer].
  404.     mov    [bx],di        ;store the next pointer.
  405.     mov    di,bx        ;save current pointer.
  406. ; bx, di -> current arg/fcn
  407. ; dx -> previous (to the left) arg/fcn
  408.     test    byte ptr -1[bx],function_marker_mask
  409.     jz    scan_rpar_1
  410.     mov    al,-1[bx]
  411.     mov    fcn_save,al        ;remember the type of function.
  412.     mov    prev_fcn,dx
  413.     mov    fbgn,bx
  414.     call    check_breakchar        ;check for a break.
  415.     jnc    got_break_char        ;got it.
  416.     call    trace_invoke        ;destroys al
  417. ;remember that fbgn is really one more than the space taken by the function.
  418.     mov    ax,[bx]            ;get pointer to first arg.
  419.     sub    ax,bx            ;compute length of name
  420.     cmp    ax,2 + mark_overhead    ;two character function name?
  421.     jne    default_to_cl        ;no - must be default.
  422.     mov    ax,2[bx]        ;get function name.
  423.     extrn    store_debug: near
  424.     call    store_debug
  425.     mov    di,offset function_name_table
  426.     mov    cx,offset function_name_length
  427.     repne    scasw
  428.     jne    default_to_cl        ;if not found, default
  429.     sub    di,offset function_name_table
  430.     ret
  431. default_to_cl:
  432.     mov    ax,'d*'
  433.     call    store_debug
  434.     mov    di,0
  435.     ret
  436. got_break_char:
  437.     jmp    init_ids
  438.  
  439. ;return data routines here
  440.  
  441.     public    return_null
  442. return_null:
  443.     mov    cx,0
  444.     call    trace_result    ;destroys al
  445. return_nothing:
  446.     mov    si,data_bottop
  447.     mov    di,fbgn
  448.     dec    di
  449.     mov    dx,prev_fcn
  450.     ret
  451.  
  452.  
  453.     public    return_string
  454. return_string:
  455. ;al=string number to return, bx=>list of strings.
  456.     add    al,al
  457.     mov    ah,0
  458.     add    bx,ax
  459.     mov    si,[bx]
  460.     mov    cx,[bx+2]
  461.     sub    cx,si
  462.     jmp    return_sicx
  463.  
  464.  
  465.     public    return_tos
  466. return_tos:
  467. ;tos -> string, di -> byte after end of string
  468.     pop    si
  469.     mov    cx,di
  470.     sub    cx,si
  471.     jmp    short return_sicx
  472.  
  473.  
  474.     public    make_active
  475. make_active:
  476. ;force a function's return value to be active.
  477. ;return zr if the function already was active.
  478.     cmp    fcn_save,active_marker
  479.     mov    fcn_save,active_marker
  480.     ret
  481.  
  482.  
  483.     public    return_arg_active
  484. return_arg_active:
  485.     mov    fcn_save,active_marker
  486. ;falls through
  487. ;
  488.     public    return_arg
  489. return_arg:
  490. ;enter with cx = number of arg to return.
  491.     call    getarg
  492. ;fall through to return_sicx
  493.  
  494.  
  495.     public    return_sicx
  496. return_sicx:
  497. ;si -> string, cx = count.
  498.     cmp    fcn_save,active_marker    ;active or neutral
  499.     jne    return_neutral
  500. ;    jmp    return_active        ;fall through!
  501.  
  502.  
  503.     public    return_active
  504. return_active:
  505. ;we need to move [si] count cx
  506. ; to [data_bottop-cx] through [data_bottop-1] reverse
  507. ;Then we return si = [data_bottop-cx], di=fbgn-1
  508.     call    trace_result    ;destroys al
  509.     jcxz    return_nothing    ;quick check for 0 chars.
  510.     mov    di,data_bottop
  511.     dec    di
  512.     add    si,cx        ;point si to end of string + 1.
  513.     dec    si        ;remember, it's postdecrement.
  514.     std            ;reverse move
  515.     rep    movsb
  516.     cld            ;everybody assumes it's cleared.
  517.     inc    di        ;make di -> last byte moved.
  518.     mov    si,di        ;si -> what we just moved.
  519.     mov    di,fbgn        ;remove previous function.
  520.     dec    di
  521.     mov    dx,prev_fcn
  522.     ret
  523.  
  524.     public    return_neutral
  525. return_neutral:
  526. ;we need to move [si] count cx
  527. ; to [fbgn-1] through [fbgn-1] - (cx - 1)
  528. ;Then we return si=data_bottop, di=[fbgn-1] - cx
  529.     call    trace_result    ;destroys al
  530.     jcxz    return_nothing    ;quick check for 0 chars.
  531.     mov    di,fbgn
  532.     dec    di
  533.     cmp    di,si        ;is it there already?
  534.     je    return_neutral_1    ;yes, save some time.
  535.     movmem            ;put it there.
  536. return_neutral_1:
  537. ;tricky time!  If we performed the movsb, cx is zero, so we're doing
  538. ;nothing.  If we took the jump to return_neutral_1, cx is the proper
  539. ;count, so di will point to the right place.
  540.     add    di,cx
  541.     mov    si,data_bottop
  542.     mov    dx,prev_fcn
  543.     ret
  544.  
  545.  
  546.     extrn    trace_result: near
  547.     extrn    trace_invoke: near
  548.  
  549. ;utility subroutines
  550.  
  551.  
  552.     extrn    check_breakchar: near
  553.  
  554.  
  555.     public    getarg1, getarg
  556. getarg1:    mov    cx,1
  557.  
  558. ;fall through to getarg
  559.  
  560. getarg:
  561.  
  562. ;enter with cx = number of argument to get.
  563. ;exit with si -> argument, cx=length of argument.
  564.  
  565. comment /****************************************************************
  566.  
  567. The pointer after the last supplied argument points to itself, which allows
  568. us to loop at getarg_loop until we think that we have found the argument.  Of
  569. course, if that argument has not been supplied, all that we've done is to chase
  570. the last pointer a few times.  As an aside, had you ever noticed that when the
  571. amount of comments exceeds the amount of code, the code is likely to be
  572. confusing?  Well, this code is probably confusing.
  573.  
  574. *************************************************************************/
  575.     mov    si,fbgn
  576.     jcxz    getarg_2    ;skip loop if count is zero.
  577. getarg_loop:
  578.     mov    si,[si]        ;get our argument
  579.     loop    getarg_loop
  580. getarg_2:
  581.     mov    cx,[si]        ;get cx=next argument
  582.     sub    cx,si        ;get cx=length of our argument
  583.     jcxz    getarg_1    ;in case we ran into fend, it doesn't matter what si -> to.
  584.     sub    cx,mark_overhead
  585.     add    si,mark_overhead-1    ;make si-> text of argument.
  586. getarg_1:
  587.     ret
  588.  
  589.  
  590.   if timing
  591. readtimer:
  592. ;exit with dx:ax set to the time since the last tick.
  593.     cmp    counting,0
  594.     je    readtimer_2
  595.  
  596.     mov    al,00h            ;Latch timer 0
  597.     out    043h,al
  598.     in    al,040h            ;Counter --> bx*/
  599.     mov    ah,al            ;LSB in BL
  600.     in    al,040h
  601.     xchg    ah,al
  602.     not    ax            ;Need ascending counter
  603.  
  604. readtimer_2:
  605.     ret
  606.   endif
  607.  
  608.  
  609. code    ends
  610.  
  611.     end
  612.  
  613.